		TITLE	UNEXE - Copyright (c) SLR Systems 1992

;		INCLUDE	MACROS

OFF		EQU	OFFSET
SEGM		EQU	(WORD PTR 2)
OFFS		EQU	(WORD PTR 0)

PACK		SEGMENT PARA PUBLIC 'UNPACK_DATA'

		ASSUME	NOTHING,CS:PACK

ifdef	pass2

		PUBLIC	EXEUNPACK,EXEPACK_PARAS,PACK_LEN,START_ADR,INITIAL_COUNT
		PUBLIC	STACK_ADR

EXEUNPACK_START:

		DW	EXE_START_JMP
EXEUNPACK:
		DB	87H,0C0H
		;
		;STACK IS WHERE I WANT IT...
		;
		PUSHM	ES,DI,DS,SI,DX,CX,BX,AX
		PUSHF
		CLD
		MOV	DX,ES			;PSP
		ADD	DX,10H
		PUSH	SS
		POP	ES
		PUSH	CS
		POP	DS
		ASSUME	DS:PACK
		ADD	STACK_ADR.SEGM,DX
		ADD	START_ADR.SEGM,DX
		XOR	SI,SI
		XOR	DI,DI
		MOV	CX,PACK_LEN/2+1
		REP	MOVSW
		PUSH	ES
		MOV	AX,OFF EXE_MOVE_REST
		PUSH	AX
		MOV	BP,1
		RETF

EXE_MOVE_REST	PROC
		;
		;MOVE COMPRESSED DATA UP SO WE CAN EXPAND DOWN...
		;
		STD
		MOV	BX,EXEPACK_PARAS	;# OF PARAGRAPHS TO MOVE...
		ASSUME	DS:NOTHING
1$:
		;
		;MOVE SMALLER OF BX AND 1000H PARAS
		;
		MOV	CX,1000H		;ASSUME 64K
		CMP	BX,CX
		JA	2$
		MOV	CX,BX
2$:
		SUB	BX,CX
		MOV	AX,DS
		SUB	AX,CX
		MOV	DS,AX
		MOV	AX,ES
		SUB	AX,CX
		MOV	ES,AX
		ADD	CX,CX
		ADD	CX,CX
		ADD	CX,CX			;# OF WORDS TO MOVE
		MOV	DI,CX
		DEC	DI
		ADD	DI,DI			;ADDRESS OF FIRST WORD TO MOVE
		MOV	SI,DI
		REP	MOVSW
		OR	BX,BX
		JNZ	1$
		CLD
		PUSH	ES
		POP	DS
		LEA	SI,2[DI]
		MOV	ES,DX
		XOR	DI,DI
		MOV	AX,INITIAL_COUNT
		JMP	L1_25

EXE_MOVE_REST	ENDP

DO_STARTUP:
		;
		;SET UP REGS AND SUCH FOR STARTING UP...
		;
		POPF
		POPM	AX,BX,CX,DX,SI,DS,DI,ES
		CLI
		MOV	SS,STACK_ADR.SEGM
		MOV	SP,STACK_ADR.OFFS
		STI
EXE_START_JMP:
		NOP
		JMP	START_ADR

REPEAT_2:
		;
		;REPEAT 2 BYTE AX TIMES
		;
		SUB	AX,0A000H-1
		XCHG	AX,CX
		LODSW
		TEST	DI,BP
		JNZ	RPT_2_A
RPT_2_B:
		REP	STOSW
		JMP	EXE_1

RPT_2_A:
		STOSB
		XCHG	AL,AH
		DEC	CX
		REP	STOSW
		STOSB
		JMP	EXE_1

DO_SEGMENTS	PROC
		;
		;
		;
		LODSW			;# OF SEGMENT CHAINS
		XCHG	AX,CX
		JCXZ	DO_STARTUP
		PUSHM	ES,DI
		LODSW			;BASE PARAGRAPH FOR REFERENCE
		ADD	AX,DX		;ADD IN PSP
		MOV	ES,AX
1$:
		LODSW			;HEAD OF CHAIN
		XCHG	AX,DI
		LODSW			;TARGET PARAGRAPH
		ADD	AX,DX
		INC	DI
		EVEN
2$:
		MOV	BX,AX
		XCHG	ES:-1[DI],BX
		MOV	DI,BX
		INC	DI
		JNZ	2$
		LOOP	1$
		POPM	DI,ES

DO_SEGMENTS	ENDP

EXE_1:
		;
		;DS:SI POINTS TO SOURCE, ES:DI POINTS TO DESTINATION
		;
		;ADJUST SEGMENTS AND OFFSETS
L1:
		OR	SI,SI
		JS	L1_1A
L1_1:
		OR	DI,DI
		JS	L1_2A
L1_2:
		;
		;EXECUTE NEXT
		;
		;    0 - 7FFF	;MOVE THAT MANY BYTES
		; 8000 - 9FFF	;REPEAT 1 BYTE THAT MANY TIMES
		;
		LODSW
L1_25:
		OR	SI,SI
		JS	L1_3A
L1_3:
		OR	AX,AX
		JNS	MOVE_STANDARD_BYTES
		CMP	AX,0A000H
		JC	REPEAT_1
		CMP	AX,0E000H
		JC	REPEAT_2
		INC	AX
		JZ	DO_SEGMENTS
REPEAT_4:
		SUB	AX,0E000H
		XCHG	AX,CX
R_4_L:
		MOVSW
		MOVSW
		SUB	SI,4
		LOOP	R_4_L
		ADD	SI,4
		JMP	EXE_1

;		ALIGN	4
L1_1A:
		SUB	SI,8000H
		MOV	AX,DS
		ADD	AX,800H
		MOV	DS,AX
		JMP	L1_1

;		ALIGN	4
L1_2A:
		SUB	DI,8000H
		MOV	AX,ES
		ADD	AX,800H
		MOV	ES,AX
		JMP	L1_2

L1_3A:
		SUB	SI,8000H
		MOV	CX,DS
		ADD	CH,8H
		MOV	DS,CX
		JMP	L1_3

MOVE_STANDARD_BYTES:
		;
		;AX IS # OF BYTES TO MOVE-1
		;
		XCHG	AX,CX
		INC	CX
		TEST	SI,BP
		JNZ	MSB_1
MSB_2:
		SHR	CX,1
		REP	MOVSW
		ADC	CX,CX
		REP	MOVSB
		JMP	EXE_1

MSB_1:
		MOVSB
		LOOP	MSB_2
		JMP	EXE_1

REPEAT_1:
		;
		;REPEAT 1 BYTE AX TIMES
		;
		SUB	AX,8000H-1
		XCHG	AX,CX
		LODSB
		MOV	AH,AL
		TEST	DI,BP
		JNZ	RPT_1_A
RPT_1_B:
		SHR	CX,1
		REP	STOSW
		ADC	CX,CX
		REP	STOSB
		JMP	EXE_1

RPT_1_A:
		STOSB
		LOOP	RPT_1_B
		JMP	EXE_1

		EVEN

STACK_ADR	DD	?
START_ADR	DD	?
EXEPACK_PARAS	DW	?
INITIAL_COUNT	DW	?

PACK_LEN	EQU	$-EXEUNPACK_START

PACK		ENDS

		END

